<?php


namespace think\restful\jwt;


use think\restful\Base;
use Firebase\JWT\JWT as BaseJWT;
use think\restful\exception\ApiException;

class Jwt extends Base
{
    protected static $initClass;

    protected $jwtConfig = [
        "iss" => "", //签发者
        "aud" => "", //jwt所面向的用户
        "iat" => 0, //签发时间
        "nbf" => 0,  //在什么时间之后该jwt才可用
        'exp' => 0, //过期时间-10min
        'data' => [  // 角色授权数据
            'userid' => 0,
            'username' => 'user'
        ]
    ];

    public function __construct()
    {
        parent::__construct();
    }

    public static function initClass(): Jwt
    {
        if (!isset(static::$initClass)) {
            static::$initClass = new static();
        }
        return static::$initClass;
    }

    /**
     * 创建JWT函数
     * @param array $token
     * @param string $key
     * @return bool
     */
    public static function encode(array $token, string $key)
    {
        if (empty($token) or empty($key))  ApiException::exception('$token 或 $key 不能为空~');
        $auth = static::initClass();
        $diff_key = array_diff_key($auth->jwtConfig, $token);
        if (empty($diff_key)){
            return BaseJWT::encode($token, $key, $auth->config['API_AUTHORIZATION_TYPE']);
        }
        return false;
    }

    /**
     * @param string $jwt
     * @param string $key
     * @return mixed
     */
    public static function decode(string $jwt,string $key):?array
    {
        if (empty($jwt) or empty($key)) ApiException::exception('$jwt 或 $key 不能为空~');
        $auth = static::initClass();
        $token = BaseJWT::decode($jwt, $key, array($auth->config['API_AUTHORIZATION_TYPE']));
        return empty($token)?[]:json_decode(json_encode($token),true);
    }

    /**
     * 验证JWT是否正确
     * @param array $data
     * @param string $jwt
     * @param string $key
     * @return bool
     */
    public static function verify(array $data,string $jwt,string $key)
    {
        if(empty($data) or empty($jwt) or empty($key)) ApiException::exception('$data、$jwt 或 $key 不能为空~');
        if ($data == static::decode($jwt, $key)['data']) {
            return true;
        }
        return false;
    }

    /**
     * 刷新JWT
     * @param $jwt
     * @param string $key 加密key
     * @param int $overtime 延长时间，默认600
     * @return array|bool   返回刷新后的JWT，还有新的TOKEN
     */
    public static function reset($jwt,string $key, int $overtime = 600)
    {
        if(empty($jwt) or empty($key)) ApiException::exception('$jwt 或 $key 不能为空~');
        $token = static::decode($jwt, $key);
        $newTime = time();
        $token['iat'] = $newTime;
        $token['nbf'] = $newTime + 10;
        $token['exp'] = $newTime + $overtime;
        return ['jwt' => static::encode($token, $key), 'token' => $token];
    }



}